<?php

namespace app\admin\service\admin;

use app\admin\model\admin\I18n as I18nModel;
use app\common\Constants;
use app\common\exception\BusinessException;
use app\common\facade\StrHelper;
use app\common\facade\TreeHelper;
use think\facade\Db;
use think\facade\Log;

class I18nService
{
    /**
     * 系统支持的语言类型
     * @return \think\Collection
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function getLangList(): \think\Collection
    {
        $langs = I18nModel::group('lang_code')
            ->field('lang_code as code')
            ->select();
        return $langs;
    }


    // menu.demo.test-field1.title
    public static function deleteTranslation($controller)
    {
        $menuNames = StrHelper::getMenuNames($controller);
        $start_with = $menuNames['lang_prefix'];
        Db::name('admin_i18n')->where('key', 'like', $start_with . '%')->delete();
    }

    // 获取指定语言的所有翻译 （树形结构，需要查询叶子节点）
    public static function fetchTranslationsFromDb($code): array
    {
        $data = Db::name('admin_i18n')->alias('t1')
            ->where('lang_code', '=', $code)
            // 筛选出有值的(对于刚创建的命名空间他肯定是没值的，就过滤掉了)
            ->whereNotNull('t1.value')
            // 这仅仅是过滤掉了已经有语言的节点的命名空间了，对于刚创建的命名空间，就办法过滤
            ->whereNotExists(function ($query) {
                $query->name('admin_i18n')->alias('t2')->where('t2.pid = t1.id')->field('t2.id');
            })->field('key, value')->select()->toArray();

        // 转换为嵌套数组格式
        return self::convertToNestedArray($data);
    }

    /**
     * 将数据库数据转换为嵌套数组格式
     * @param array $data
     * @return array
     */
    public static function convertToNestedArray($data): array
    {
        $result = [];

        foreach ($data as $item) {
            // 确保 key 是字符串且不为空
            $key_string = (string)($item['key'] ?? '');
            if (empty($key_string)) {
                // 如果 key 为空，跳过此项，避免处理无效键
                continue;
            }

            $keys = explode('.', $key_string);
            $current = &$result; // 使用引用，以便修改 $result

            foreach ($keys as $index => $key_part) {
                // 确保每个键部分都是有效的字符串，并去除首尾空格
                $key_part = trim((string)$key_part);

                // 如果键部分为空，则跳过此部分。这可以防止生成类似 [0 => 'part1', 1 => '', 2 => 'part2'] 的数组，
                // 从而避免 Undefined array key 1 的问题。
                if ($key_part === '') {
                    continue;
                }

                // 如果不是路径中的最后一个键
                if ($index < count($keys) - 1) {
                    // 确保当前键对应的值是一个数组。
                    // 如果不存在，或者存在但不是数组，则将其初始化为空数组。
                    if (!isset($current[$key_part]) || !is_array($current[$key_part])) {
                        $current[$key_part] = [];
                    }
                    // 移动到下一个嵌套级别
                    $current = &$current[$key_part];
                } else {
                    // 这是路径中的最后一个键，直接赋值
                    // 如果当前位置已经是一个数组（意味着它有子节点），
                    // 那么我们将当前值存储在一个特殊的键下（例如 '_value'）。
                    // 否则，直接赋值。
                    // 考虑到您提供的 zh_array.php 示例，似乎没有父键同时有值和子键的情况，
                    // 因此这里保持直接赋值，不引入 _value。
                    // $current[$key_part] = $item['value'];

                    // 在这里进行转换：将 :attribute 替换为 {attribute}
                    $transformedValue = preg_replace('/:(\w+)/', '{$1}', $item['value']);

                    $current[$key_part] = $transformedValue;

                }
            }
        }

        return $result;
    }


    public static function saveNamespaceData($post): void
    {
        if (empty($post['pid'])) {
            $post['pid'] = 0;
        }
        $langs = I18nModel::field('lang_code as code')->distinct()->select()->toArray();
        if (empty($langs)) {
            $langs = [
                ['code' => 'zh-cn',],
                ['code' => 'en',],
            ];
        }
        foreach ($langs as $lang) {
            $data = [
                'pid' => $post['pid'],
                'segment' => $post['segment'],
                'lang_code' => $lang['code'],
                'value' => null,
                'is_leaf' => 0,
                'status' => 1,
                'lang_key' => TreeHelper::findParentNames($post['pid'], 'admin_i18n', '.', 'id', 'pid', 'segment'),
                'pids' => TreeHelper::findParentIds($post['pid'], 'admin_i18n'),
            ];
            I18nModel::create($data);
        }
    }

    public static function checkAndCreateNamespace($path): bool
    {
        $parts = explode('.', $path);
        $partsToProcess = array_slice($parts, 0, -1);

        $langs = I18nModel::field('lang_code as code')->distinct()->select()->toArray();
        $currentPath = '';
        $current_pid = 0;
        $last_id = 0;
        foreach ($partsToProcess as $part) {
            if (!empty($currentPath)) {
                $currentPath .= '.';
            }
            $currentPath .= $part;
            $exists = I18nModel::where('key', '=', $currentPath)
                ->where('is_leaf', '=', 0)
                ->findOrEmpty();
            if ($exists->isEmpty()) {
                foreach ($langs as $lang) {
                    $data = I18nModel::create([
                        'pid' => $current_pid,
                        'segment' => $part,
                        'code' => $lang,
                        'lang_key' => TreeHelper::findParentNames($current_pid, 'admin_i18n', '.', 'id', 'pid', 'segment'),
                        'pids' => TreeHelper::findParentIds($current_pid, 'admin_i18n'),
                    ]);
                    $last_id = $data->id;
                }
            }
        }


        return true;
    }

    /**
     * 保存语言数据
     * @param $key
     * @param $data
     * @return bool
     */
    public static function asyncTranslationData($key, $data): bool
    {
        foreach ($data as $code => $value) {
            self::addTranslationCascade($key, $value, $code);
        }
        return true;
    }


    /**
     * 级联添加翻译数据
     * @param $key
     * @param $value
     * @param $langCode
     * @return array
     * @throws BusinessException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function addTranslationCascade($key, $value, $langCode): array
    {
        $keyParts = explode('.', $key);
        $currentKeyPath = [];
        $result = [];
        // 遍历键的每一部分
        foreach ($keyParts as $i => $part) {
            $currentKeyPath[] = $part;
            // 键存在多个父级
            if (count($currentKeyPath) > 1) {
                $parentKey = implode('.', array_slice($currentKeyPath, 0, -1));
                trace($parentKey, '父级节点key');
                trace(implode('.', $currentKeyPath), '当前节点key');
                $parent = Db::name('admin_i18n')
                    ->where(['key' => $parentKey, 'lang_code' => $langCode])
                    ->find();
                $pid = empty($parent) ? 0 : $parent['id'];
                if (empty($parent)) {
                    trace($parentKey, '无父级节点开始创建');
                    $parentKeyArr = explode('.', $parentKey);
                    $data = [
                        'pid' => $pid,
                        'segment' => end($parentKeyArr),
                        'lang_code' => $langCode,
                        'value' => null,
                        'is_leaf' => 0,
                        'status' => 1,
                        'lang_key' => \app\common\facade\TreeHelper::findParentNames($pid, 'admin_i18n', '.', 'id', 'pid', 'segment'),
                        'pids' => \app\common\facade\TreeHelper::findParentIds($pid, 'admin_i18n'),
                    ];
                    $translationInfo = I18nModel::create($data);
                    $pid = $translationInfo['id'];
                    $result['branch'][] = $translationInfo->toArray();
                } else {
                    trace($parentKey, '父级节点已存在');
                    if ($parent['value'] && $parent['is_leaf'] === 1) {
                        throw new BusinessException('不可以在叶子节点创建节点');
                    }
                }
                $currentKey = implode('.', $currentKeyPath);
                trace($currentKey, '父级节点已经存在检查当前节点');
                $current = Db::name('admin_i18n')
                    ->where(['key' => $currentKey, 'lang_code' => $langCode])
                    ->find();
                if (empty($current)) {
                    trace($currentKey, '当前节点不存在现在创建');
                    $isLeaf = ($i == count($keyParts) - 1) ? 1 : 0;
                    $nodeValue = $isLeaf ? $value : null;
                    $data = [
                        'pid' => $pid,
                        'segment' => end($currentKeyPath),
                        'lang_code' => $langCode,
                        'value' => $nodeValue,
                        'is_leaf' => $isLeaf,
                        'status' => 1,
                        'lang_key' => \app\common\facade\TreeHelper::findParentNames($pid, 'admin_i18n', '.', 'id', 'pid', 'segment'),
                        'pids' => \app\common\facade\TreeHelper::findParentIds($pid, 'admin_i18n'),
                    ];
                    $translationInfo = I18nModel::create($data);
                    if ($isLeaf === 1) {
                        $result['leaf'][] = $translationInfo->toArray();
                    } else {
                        $result['branch'][] = $translationInfo->toArray();
                    }
                } else {
                    trace($currentKey, '当前节点已存在');
                    // 如果当前节点已存在，并且是叶子节点，则更新其值
                    if ($current['is_leaf'] === 1) {
                        Db::name('admin_i18n')
                            ->where(['id' => $current['id']])
                            ->update(['value' => $value]);
                        $current['value'] = $value;
                        $result['leaf'][] = $current;
                    } else {
                        // 如果是分支节点，不更新其值，但可以记录到结果中
                        $result['branch'][] = $current;
                    }
                }
            }
        }
        trace(json_encode($result), '创建结果');
        return $result;
    }


}